import {
  Injectable,
  ExecutionContext,
  UnauthorizedException,
} from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { AuthGuard } from '@nestjs/passport';
import { Observable } from 'rxjs';
import { SKIP_LOGIN } from '../decorator/public.decorator';

@Injectable()
export class JwtAuthGuard extends AuthGuard('jwt') {
  constructor(private reflector: Reflector) {
    super();
  }

  async canActivate(context: ExecutionContext): Promise<boolean> {
    const request = context.switchToHttp().getRequest();
    const isPublic = this.reflector.getAllAndOverride<boolean>(SKIP_LOGIN, [
      context.getHandler(),
      context.getClass(),
    ]);

    if (isPublic) {
      try {
        const result = (await super.canActivate(context)) as boolean;
        return result; // req上自带user对象
      } catch (e) {
        // 验证失败时允许访问，但不设置用户信息
        request.user = null; // 明确标记用户未登录
        return true;
      }
    }

    return (await super.canActivate(context)) as boolean;
  }

  // 策略走完会调用此函数，不管成功还是失败
  // 处理认证失败的情况（handleRequest方法是AuthGuard类中的一个特定方法）
  handleRequest(
    err: any,
    user: any,
    info: any,
    context: ExecutionContext,
    status?: any,
  ) {
    if (err || !user) throw new UnauthorizedException(`未登录`);

    return user;
  }
}
